import { defineStore } from 'pinia'
import type { LoginParamsData, UserInfoData } from '@/api/userInfo'
import { default as userInfoApi } from '@/api/userInfo'
import {allAsyncRoutes, anyRoute, staticRoutes} from '@/router/routes'
import type { RouteRecordRaw } from 'vue-router'
import router from '@/router'
import cloneDeep from 'lodash/cloneDeep'


interface UserInfoStoreStateData {
  token: string,
  userInfo: UserInfoData,
  menuRoutes:Array<RouteRecordRaw>
}


function initUserInfo(target: UserInfoData, source: UserInfoData) {
  Object.assign(target, source)
}

// 定义函数从所有的异步路由当中过滤当前用户的异步路由
function filterAsyncRoutes(allAsyncRoutes:RouteRecordRaw[],routeNames:string[]){
  let asynRoutes = allAsyncRoutes.filter(item=>{
    // if(routeNames.indexOf(item.name as string) !==-1){
    //   // 还要递归拿去二级路由
    //   if(item.children&&item.children.length){
    //     item.children=filterAsyncRoutes(item.children,routeNames)
    //   }
    //   return true
    // }
    if(routeNames.includes(item.name as string)){
      // 还要递归拿去二级路由
      if(item.children&&item.children.length){
        item.children=filterAsyncRoutes(item.children,routeNames)
      }
      return true
    }
  })
  return asynRoutes
}

// 封装可以一次性添加多个路由的工具函数
// 使用了router的addRoute方法
function addRoutes(userAsyncRoutesAndAnyRoute:RouteRecordRaw[]){
  userAsyncRoutesAndAnyRoute.forEach(item=>{
    router.addRoute(item)
  })
}

// 当用户退出登录的时候，我们需要重置路由
function resetRoutes(){
  // 删除所有的路由
  let routes = router.getRoutes()
  routes.forEach(item => {
    router.removeRoute(item.name as string)
  });
  // 添加静态路由
  addRoutes(staticRoutes)
}





export const useUserInfoStore = defineStore('userInfo', {
  // 核心概念
  state: (): UserInfoStoreStateData => {
    return {
      // token到时候要和自动登录（免登录）相关联
      // 存储token到localStorage持久化存储
      // cookie  localStorage  sessionStorage的区别
      token: localStorage.getItem('token_key') || '',
      userInfo: {
        routes: [],
        buttons: [],
        roles: [],
        name: '',
        avatar: ''
      },
      menuRoutes:staticRoutes
    }
  },
  actions: {
    async login(loginParams: LoginParamsData) {
      try {
        const result = await userInfoApi.userLogin(loginParams)
        this.token = result.token  //把token保存在state
        // 要自动登录还得把token保存到localStorage
        localStorage.setItem('token_key', result.token)

        // 如果登录成功，我们还要写一个正常的返回值，让async函数返回的promise是成功的
        // 后面根据这个值来判断登录成功还是失败，再去做后续的操作
        return 'ok'
      } catch (error) {
        return Promise.reject('登录失败')
      }
    },

    // 根据token获取用户信息
    async getUserInfo() {
      try {
        const result = await userInfoApi.getUserInfo()
        this.userInfo = result 
        // 获取该用户的路由
        let routeNames = result.routes
        // 如下是routes的数据
// routes:Array[2]
// 0:"Product"
// 1:"Trademark"
        // 根据routes的数据获取自己动态路由
        // 先将动态路由拷贝一份,防止其他用户的动态路由不能完全生成
        let userAsyncRoutes = filterAsyncRoutes(cloneDeep(allAsyncRoutes),routeNames)
        // 将动态路由添加到路由实例当中
        // 任意路由和动态路由数组合并
        addRoutes(userAsyncRoutes.concat(anyRoute))
        // 给组件渲染的路由数组添加路由,不然页面不会显示对应的路由组件或者导航
        this.menuRoutes=staticRoutes.concat(userAsyncRoutes,anyRoute)
        return 'ok'
      } catch (error) {
        return Promise.reject('获取用户信息失败')
      }
    },

    async reset() {
      this.token = ''
      initUserInfo(this.userInfo, {
        routes: [],
        buttons: [],
        roles: [],
        name: '',
        avatar: ''
      })
      localStorage.removeItem('token_key')
    },

    async logout() {
      try {
        await userInfoApi.userLogout()
        // 退出成功我们需要把state当中的用户信息和token全部清除
        // 也得把localStorage当中的token给清除
        // this.token = ''
        // this.userInfo = {}
        // localStorage.removeItem('token_key')

        // 重置路由
        resetRoutes()
        this.reset()
        return 'ok'
      } catch (error) {
        return Promise.reject('退出失败')
      }
    }
  },
  getters: {

  }
})